// 安装 koa => npm i koa -S
// 引入 koa 并创建 Koa 实例
const Koa = require('koa');
const app = new Koa();

// 安装 koa-router => npm i koa-router -S
// 引入 koa-router 并创建 KoaRouter 实例
const KoaRouter = require('koa-router');
const router = new KoaRouter();

// 安装 koa-bodyparser => npm i koa-bodyparser -S
// 并引入，用来解析 POST 请求体数据
const bodyparser = require('koa-bodyparser');
app.use(bodyparser());

// 引入实用工具包中的公用函数
const {
    query,
    passwordEncoder,
    genToken,
    toLocalDateString,
} = require('./utility');

// 引入授权中间件，并加载到 koa 实例上
const authorize = require('./middleware/authorize');
app.use(authorize());

// 注册接口
router.post('/register', async (ctx) => {
    // 解构参数
    const { mobile, password } = ctx.request.body;
    // console.log({ mobile, password });
    // 校验手机号格式
    if (!/^1[345789]\d{9}$/.test(mobile)) {
        ctx.body = {
            code: 400,
            message: '手机号格式不正确',
        };
        return;
    }
    // 连接数据库，查看用户是否已经存在，存在了就不能注册
    let res = await query('select mobile from user where mobile = ?', [mobile]);
    // console.log(res);
    if (res.length !== 0) {
        ctx.body = {
            code: 403,
            message: '用户手机号已存在',
        };
        return;
    }
    // 保存到数据库
    res = await query('insert into user (mobile, password) values (?, ?)', [
        mobile,
        passwordEncoder(password),
    ]);
    /**
     * res: OkPacket {
            fieldCount: 0,
            affectedRows: 1,
            insertId: 1,
            serverStatus: 2,
            warningCount: 0,
            message: '',
            protocol41: true,
            changedRows: 0
        }
     */
    // console.log({ res });
    if (res.affectedRows === 0) {
        ctx.body = {
            code: 500,
            message: '注册失败，请稍后再试，或者联系管理员：13811065680',
        };
        return;
    }
    // 走到这里，就表示插入成功了
    ctx.body = {
        code: 200,
        data: {
            newId: res.insertId,
        },
        message: '注册成功',
    };
});

// 登录接口
router.post('/login', async (ctx) => {
    // 解构参数
    const { mobile, password } = ctx.request.body;
    // console.log({ mobile, password });
    // 参数非空校验
    if (!mobile || !password) {
        ctx.body = {
            code: 400,
            message: '手机号密码不能为空',
        };
        return;
    }
    // 查询数据，看看用户是否存在
    let res = await query(
        'select id, mobile, password from user where mobile = ?',
        [mobile],
    );
    // console.log(res);
    if (res.length === 0) {
        ctx.body = {
            code: 404,
            message: '用户不存在',
        };
        return;
    }
    // 走到这里，就说用用户存在，然后就是密码校验
    const user = res[0];
    if (passwordEncoder(password) !== user.password) {
        ctx.body = {
            code: 400,
            message: '用户手机号和密码不匹配',
        };
        return;
    }
    // 走到这里，说明密码也是正确，就可以登录
    // token 中一定不能把密码也放进去，不安全，总之，不能放敏感数据
    const token = genToken({ id: user.id, mobile: user.mobile });

    // 登录成功
    ctx.body = {
        code: 200,
        data: {
            token,
        },
        message: '登录成功',
    };
});

// 签到接口
router.post('/signs', async (ctx) => {
    // 因为经过了身份校验中间件，能走到这里，就说明我们可以拿到登录用户的信息了
    // console.log('签到接口', ctx.user);
    // 查询数据库，判断今天是不是已经签到了
    let res = await query(
        "select count(*) as count from sign_record where DATE_FORMAT(create_time, '%Y-%m-%d') = ?",
        [toLocalDateString(new Date())],
    );
    // res 返回一个数组，数组的第一项是一个对象，
    // 如果对象的 count 字段返回的不是 0，就说明已经签到了
    if (res[0].count !== 0) {
        ctx.body = {
            code: 403,
            message: '今天已经签到了',
        };
        return;
    }
    // 走到这里，说明今天没有签到，可以进行签到
    // 我们想数据库中，加入一条签到记录
    res = await query('insert into sign_record (uid) values (?)', [
        ctx.user.id,
    ]);
    // 通过受影响行数，来判断是否插入成功
    if (res.affectedRows === 0) {
        ctx.body = {
            code: 500,
            message: '签到失败，请稍后再试！',
        };
        return;
    }
    // 签到成功，返回成功响应
    ctx.body = {
        code: 200,
        message: '签到成功',
    };
});

// 查询已签到记录
router.get('/signs/count', async (ctx) => {
    // 查询数据库，返回签到总数
    const res = await query(
        'select count(*) as sign_num from sign_record where uid = ?',
        [ctx.user.id],
    );
    ctx.body = {
        code: 200,
        data: res[0],
        message: '请求成功',
    };
});

// 判断进入是否已完成签到
router.get('/signs/today', async (ctx) => {
    const res = await query(
        "select count(*) as count from sign_record where DATE_FORMAT(create_time, '%Y-%m-%d') = ?",
        [toLocalDateString(new Date())],
    );
    // 返回响应
    ctx.body = {
        code: 200,
        data: {
            isSign: res[0].count !== 0,
        },
        message: '请求成功',
    };
});

// 加载路由
app.use(router.routes());

// 监听端口，启动服务
const port = 3000;
app.listen(port, () => {
    console.log(`Koa server listening at http://localhost:${port}`);
});
